package de.easywakeup.appService;

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.concurrent.TimeUnit;

import android.annotation.SuppressLint;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.os.IBinder;
import android.os.PowerManager;
import android.provider.BaseColumns;
import android.provider.CalendarContract.Calendars;
import android.provider.CalendarContract.Instances;
import de.easywakeup.data.AlarmList;
import de.easywakeup.data.Data;
import de.easywakeup.gui.AlarmSettings;
import android.util.Log;
//these imports are used in the following code
import android.net.Uri;
import android.content.ContentUris;
import android.content.ContentResolver;

public class AppService extends Service
{

	private Data data;

	@Override
	public IBinder onBind( Intent intent )
	{
		// This procedure is not necessary for my purpose. It is used for
		// Bounded Services
		return null;
	}

	@Override
	public void onCreate( )
	{
		System.out.println( System.currentTimeMillis( ) + ": AppService created" );
		// Keep assignment to the rootObject
		data = Data.singleton( );
		// Set reference for this class
		data.setAppService( this );

	}

	@Override
	public int onStartCommand( Intent intent, int flags, int startId )
	{

		// If the Service started, it will call this procedure
		System.out.println( System.currentTimeMillis( ) + ": AppService started" );

		// Provides the Wakeup in sleepingmode of the mobil phone
		PowerManager pm = (PowerManager) getSystemService( Context.POWER_SERVICE );
		PowerManager.WakeLock wakeLock = pm.newWakeLock( PowerManager.PARTIAL_WAKE_LOCK, "My PARTIAL_WAKE_LOCK" );
		wakeLock.acquire( );

		// our procedures who has to be running
		getCalendarEntries( );

		// Check the daily alert according to the settings in a single alarm
		setDailyAlert( );

		// Weather Query
		// Access only, when the user entered a location. Only one check per
		// hour!
		if( !data.getLocation( ).equals( "" ) && data.getLastWheaterUpdate( ) < System.currentTimeMillis( ) - 3600000 )
		{
			data.setLastWheaterUpdate( System.currentTimeMillis( ) );
			Data.getGetWeather( ).startQuery( data.getWoeid( ) );
		}

		// If the procedure finished his job, we have to stop the Service
		wakeLock.release( );
		stopSelf( );

		// The Service should run until the operating system quit it. In this
		// case we return "START_STICKY"
		return START_STICKY;
	}

	// Set the repeating alarms for
	private void setDailyAlert( )
	{
		for( AlarmList element : data.getAlarmList( ) )
		{
			// don't overwrite the existing Alarm
			if( element.getTimer( ) == null )
			{
				switch( Calendar.DAY_OF_WEEK)
				{
					case Calendar.MONDAY:
						if( element.isBt_moClicked( ) )
						{
							element = TimerHandler.setTimer( this, element, false, 0 );
						}
						break;
					case Calendar.TUESDAY:
						if( element.isBt_diClicked( ) )
						{
							element = TimerHandler.setTimer( this, element, false, 0 );
						}

						break;
					case Calendar.WEDNESDAY:
						if( element.isBt_miClicked( ) )
						{
							element = TimerHandler.setTimer( this, element, false, 0 );
						}

						break;
					case Calendar.THURSDAY:
						if( element.isBt_doClicked( ) )
						{
							element = TimerHandler.setTimer( this, element, false, 0 );
						}

						break;
					case Calendar.FRIDAY:
						if( element.isBt_frClicked( ) )
						{
							element = TimerHandler.setTimer( this, element, false, 0 );
						}

						break;
					case Calendar.SATURDAY:
						if( element.isBt_saClicked( ) )
						{
							element = TimerHandler.setTimer( this, element, false, 0 );
						}

						break;
					case Calendar.SUNDAY:
						if( element.isBt_soClicked( ) )
						{
							element = TimerHandler.setTimer( this, element, false, 0 );
						}

						break;

					default:
						break;
				}
			}
		}
	}

	/**
	 * ask the Calender for Events. If there an Event, it sets an AlarmList
	 * Element
	 */
	@SuppressLint( "NewApi" )
	public void getCalendarEntries( )
	{
		// The query is looking for calendars that have the
		// ACCOUNT_NAME "sampleuser@google.com", the ACCOUNT_TYPE "com.google",
		// and the OWNER_ACCOUNT "sampleuser@google.com". If you want to see all
		// calendars that a user has viewed, not just calendars the user owns,
		// omit the OWNER_ACCOUNT. The query returns a Cursor object that you
		// can use to traverse the result set returned by the database query.
		// For more discussion of using queries in content providers, see
		// Content Providers.
		// Run query
		// Select calendars
		// ----------------------------------
		ContentResolver resolver = getContentResolver( );
		String[ ] projection = { BaseColumns._ID, Calendars.CALENDAR_DISPLAY_NAME };
		Cursor cursor = resolver.query( Calendars.CONTENT_URI, projection, null, null, null );
		long calenderId;
		if( cursor.moveToNext( ) )
		{
			calenderId = cursor.getLong( 0 );
			String name = cursor.getString( 1 );
			Log.i( "My", "Kalender ID " + calenderId + ": " + name );
		}
		else
		{
			throw new RuntimeException( "Kein Kalender verfuegbar" );

		}
		// Publish the calendar entries
		long now = System.currentTimeMillis( );
		Uri.Builder builder = Instances.CONTENT_URI.buildUpon( );
		ContentUris.appendId( builder, now ); // Begin Zeitraum
		ContentUris.appendId( builder, now + 1 * 24 * 60 * 60 * 1000 ); // Ende-Zeitraum
		                                                                // //1
		                                                                // Tage
		projection = new String[ ] { Instances.EVENT_ID, Instances.BEGIN, Instances.TITLE };
		cursor = resolver.query( builder.build( ), projection, null, null, null );
		while( cursor.moveToNext( ) )
		{
			long eventId = cursor.getLong( 0 );
			Date date = new Date( cursor.getLong( 1 ) );
			String title = cursor.getString( 2 );

			// add the calendar events into the alarmList
			Log.i( "My", "Event ID " + eventId + ": " + title + " (" + date + ")" );
			AlarmList al_temp = new AlarmList( );

			long calTime = calculateAutoTime( );
			long calTimeAsDate = date.getTime( ) - TimeUnit.MINUTES.toMillis( calTime );

			Date caldate = new Date( calTimeAsDate ); // given date from the
			                                          // calculated time
			Calendar calendar = Calendar.getInstance( ); // creates a
			                                             // new
			                                             // calendar
			                                             // instance
			calendar.setTime( caldate ); // assigns calendar to given date
			int hour = calendar.get( Calendar.HOUR_OF_DAY ); // gets hour in 24h
			                                                 // format. For 12h
			                                                 // format use:
			                                                 // calendar.get(Calendar.HOUR);
			calendar.get( Calendar.HOUR ); // gets hour in 12h format
			int minute = calendar.get( Calendar.MINUTE ); // gets minutes based
			                                              // on 60 Minutes
			                                              // metric

			String time = new StringBuilder( ).append( AlarmSettings.pad( hour ) ).append( ":" ).append( AlarmSettings.pad( minute ) ).toString( );

			al_temp.setAlarmTime( time );
			al_temp.setNameOfAlarmEdit( title );
			al_temp.setAlarmTimeHour( hour );
			al_temp.setAlarmTimeMinute( minute );
			// Set Alarm by time, if there any existing Time
			// set automatically a timer for the the specific time!
			if( !data.isAlarmListByTime( time ) )
			{
				// is there no existing Alarm, create a new one
				data.getAlarmList( ).add( al_temp );

				// update gui
				if( data.getMainScreen( ) != null )
				{
					data.getMainScreen( ).updateGui( );
				}
				if( data.getAdapterListViewMain( ) != null )
				{
					data.getAdapterListViewMain( ).notifyDataSetChanged( );
				}
				// Consider the Weather, if checked
				TimerHandler.setTimer( this, al_temp, false, 0 );

			}
			al_temp.setCalculatedAutoTime( TimeUnit.MINUTES.toMillis( calTime ) );
			al_temp.setCheckBoxCalenderClicked( true );

		}
	}

	/**
	 * Calculate the global time according to the temperature temperature < 10 =
	 * 20 Minutes
	 * 
	 * @return
	 */
	private int calculateAutoTime( )
	{
		int result = Integer.parseInt( data.getTimeBeforeMeeting( ) );
		int timeAutoChange = Integer.parseInt( data.getTimeAutoChange( ) );

		int temperature = Integer.parseInt( data.getTemperature( ) );

		if( data.getLocation( ).equals( "" ) )
		{
			if( temperature < 10 )
			{
				result += 20 * timeAutoChange; // If the temperature below 10
				                               // degrees, it changes it for 20
				                               // minutes in advance and
				                               // according to the sensibility
			}
			else if( temperature < 15 )
			{
				result += 10 * timeAutoChange; // Below 15 degrees = Change 10
				                               // Min + Sen.
			}
			else if( temperature < 20 )
			{
				result += 5 * timeAutoChange; // Below 20 degrees = Change 5 Min
				                              // + Sen.
			} // Is the temperature higer than 20 degrees, there won't be a
			  // change
		}
		return result;
	}

	@Override
	public void onDestroy( )
	{
		System.out.println( System.currentTimeMillis( ) + ": AppService destroyed" );

	}

}